#include"threadPool.h"
#include <mysql/mysql.h>
#include <hiredis/hiredis.h>
#include "detachCommand.h"
#include "timingWheel.h"
int exitPipe[2];
void handler(int signum){
    printf("signum = %d\n",signum);
    write(exitPipe[1],"1",1);
}

int main(int argc,char*argv[])
{
    // ./server 192.168.30.128 1234 3
    ARGS_CHECK(argc,4);

    pipe(exitPipe);
    if(fork()!= 0){
        //  父进程接收信号，通过管道给子进程发送退出信息
        close(exitPipe[0]);
        signal(SIGUSR1,handler);
        wait(NULL);
        printf("Parent is going to exit!\n");
        exit(0);
    }
    // 只有子进程才能创建线程池
    close(exitPipe[1]);
    int sockfd;
    tcpInit(argv[1],argv[2],&sockfd);

    // 创建线程池
    int workerNum = atoi(argv[3]);
    threadPool_t threadPool;
    threadPoolInit(&threadPool,workerNum);
    makeWorker(&threadPool);

    // 将sockfd加入监听
    int epfd = epoll_create(1);
    epollAdd(epfd,sockfd);

    //将exitPipe[0]加入监听，当就绪时表示要退出线程池
    epollAdd(epfd,exitPipe[0]); 

    //主线程，生产者
    //创建储存文件的目录                                                                                 
    mkdir("netDisk",0777);
    //修改当前工作目录
    chdir("netDisk");
    //连接MySQL数据库
    pthread_mutex_lock(&threadPool.mutex);
    MYSQL* mysql;
    mysql = mysql_init(NULL);
    int ret = connectMySQL(mysql);
    pthread_mutex_unlock(&threadPool.mutex);
    if(ret == -1){
        printf("Error:mysqlConnection\n");
        return -1;
    }
    //连接Redis数据库
    redisContext* redis = connectRedis();
    if(redis == NULL){
        printf("Error:redisConnection\n");
        return -1;
    }
    //创建netfd和pCmdShare的映射关系
    cmdShare_t* netfdToPcmd[1024]={0};

    //创建使用超时断开连接的数据结构
    timeoutShare_t timeoutShare;
    timeoutShareInit(&timeoutShare,30);

    while(1){
        struct epoll_event readySet[1024];
        int readyNum = epoll_wait(epfd,readySet,1024,1000);
        //设置当前要处理的集合所在队列的下标
        int idx = time(NULL)%(timeoutShare.loopQueue.queueSize);
        setTimeoutIdx(&timeoutShare,idx);
        /* printf("timeoutShare.Idx = %d\n",timeoutShare.Idx); */
        if(readyNum >0){
            for(int i=0;i<readyNum;++i){
                if(readySet[i].data.fd == sockfd){
                    int netfd = accept(sockfd,NULL,NULL);
                    SYSTEM_LOG(LOG_NOTICE,"","logging...");
                    printf("I got 1 task,netfd = %d!\n",netfd);
                    //加入监听
                    epollAdd(epfd,netfd);
                    //将netfd加入超时集合
                    joinSet(&timeoutShare,netfd);

                }else if(readySet[i].data.fd == exitPipe[0]){
                    //释放redis连接
                    disconnectRedis(redis);
                    //清空pCmdshrare
                    for(int idx =0;idx < 1024;++idx){
                        if(netfdToPcmd[idx]!=NULL){
                            free(netfdToPcmd[idx]);
                            netfdToPcmd[idx] = NULL;
                        }
                    }
                    // 退出线程池
                    for(int j = 0;j<threadPool.tidArr.workerNum;++j){
                        pthread_cancel(threadPool.tidArr.arr[j]);
                    }

                    //修改退出标志位，要加锁，并唤醒条件变量
                    pthread_mutex_lock(&threadPool.mutex); 
                    threadPool.exitFlag =1; 
                    pthread_cond_broadcast(&threadPool.cond);
                    pthread_mutex_unlock(&threadPool.mutex); 
                    for(int j = 0;j<threadPool.tidArr.workerNum;++j){ 
                        pthread_join(threadPool.tidArr.arr[j],NULL); 
                    } 
                    printf("main thread is going to exit!\n");
                    exit(0);
                }else if(readySet[i].data.fd!=0){
                    //除了登录注册之外的短命令
                    int netfd = readySet[i].data.fd;
                    //进行长短命令分离
                    commandDetach(netfd,epfd,mysql,redis,netfdToPcmd,&threadPool,&timeoutShare);    
                }
            }
        }else{
            /* printf("timeout!\n"); */
            //清空超时集合
            int idx = time(NULL)%(timeoutShare.loopQueue.queueSize);
            emptySet(&timeoutShare,netfdToPcmd,idx);
        }
    }
    return 0;
}

